package hhm.javamode.base.clipboard;

import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;

import hhm.javamode.watcher.ConcreteWatcher;
import hhm.javamode.watcher.Watched;
import hhm.javamode.watcher.Watcher;

/**
 * 剪贴板监控器 负责对剪贴板的监控和操作 由于监控需要一个对象作为ClipboardOwner，故不能用静态类
 * 不用FlavorListener是因为它仅监控剪贴板中数据类型的变化
 */
public class SystemClipboardMonitor implements ClipboardOwner, Watched {
	private Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
	// 存放观察者
	private List<Watcher> list = new ArrayList<Watcher>();

	public static void main(String[] args) {

		// 将剪贴板中内容的ClipboardOwner设置为自己
		// 这样当其中内容变化时，就会触发lostOwnership事件
		SystemClipboardMonitor systemClipboardMonitor = new SystemClipboardMonitor();
		systemClipboardMonitor.clipboard.setContents(systemClipboardMonitor.clipboard.getContents(null),
				systemClipboardMonitor);

		new JFrame().setVisible(true);// 软件窗口

	}

	/*******************************************
	 * 如果剪贴板的内容改变，则系统自动调用此方法 *
	 *******************************************/

	@Override
	public void lostOwnership(Clipboard clipboard, Transferable contents) {

		// 如果不暂停一下，经常会抛出IllegalStateException
		// 猜测是操作系统正在使用系统剪切板，故暂时无法访问
		try {
			Thread.sleep(1);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		// 取出文本并进行一次文本处理
		// 如果剪贴板中有文本:
		if (clipboard.isDataFlavorAvailable(DataFlavor.stringFlavor)) {
			try {

				String newText = "";
				try {

					newText = (String) clipboard.getData(DataFlavor.allHtmlFlavor);
				} catch (java.awt.datatransfer.UnsupportedFlavorException e) {
					newText = (String) clipboard.getData(DataFlavor.stringFlavor);
				}
				// 存入剪贴板，并注册自己为所有者
				// 这样下次剪贴板内容改变时，仍然可以触发此事件
				StringSelection tmp = new StringSelection(newText);
				clipboard.setContents(tmp, this);

				// 通知观察者
				//注册一个观察者，把消息发给他
				addWatcher(new ConcreteWatcher());
				notifyWatchers(newText);

			} catch (UnsupportedFlavorException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		} else {
			// 如果剪贴板中没有文本，仍然将自己设置为它的ClipboardOwner
			clipboard.setContents(clipboard.getContents(null), this);
		}

	}

	@Override
	public void addWatcher(Watcher watcher) {
		list.add(watcher);

	}

	@Override
	public void removeWatcher(Watcher watcher) {
		list.remove(watcher);

	}

	@Override
	public void notifyWatchers(String str) {
		// TODO Auto-generated method stub
		for (Watcher watcher : list) {
			watcher.update(str);
		}
	}

}
